package org.example.memora.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.example.memora.DTO.PostCreateDTO;
import org.example.memora.DTO.UserRedisDTO;
import org.example.memora.DTO.request.PostSearchRequest;
import org.example.memora.common.result.Result;
import org.example.memora.entity.Post;
import org.example.memora.entity.PostCategory;
import org.example.memora.entity.vo.PostVO;
import org.example.memora.mapper.PostCategoryMapper;
import org.example.memora.service.PostService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.example.memora.DTO.PostDTO;
import org.example.memora.common.utils.UserHolder;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;


/**
 * @author YYJ
 */
@RestController
@RequestMapping("/api/posts")
@Tag(name = "帖子管理", description = "提供帖子的新增、查询、删除等接口")
public class PostController {
    @Autowired
    private PostService postService;
    @Autowired
    private PostCategoryMapper postCategoryMapper;

    /**
     * GET /api/posts/recommended
     * 请求信息: 分页参数 page, size; 可选分类ID category_id
     * 返回结果: posts（分页对象）
     * API说明: 首页推荐接口，根据用户信息及帖子分类获取个性化推荐帖子
     */
    @Operation(
            summary = "获取首页推荐帖子",
            description = "根据当前登录用户信息及帖子分类，返回推荐的帖子列表，支持分页"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功，返回推荐帖子分页数据"),
            @ApiResponse(responseCode = "401", description = "用户未登录"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/recommended")
    public Result<Page<PostVO>> getRecommendedPosts(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size,
            @RequestParam(value = "category_id", required = false) String categoryId) {
        UserRedisDTO userRedisDTO = UserHolder.getUser();
        if(userRedisDTO==null){
            return Result.error("未登录账号，请先登录");
        }
        String userId=String.valueOf(userRedisDTO.getUserId());
        Page<Post> recommendedPosts = postService.getRecommendedPosts(userId, page, size, categoryId);
        // 构建 VO 分页对象
        Page<PostVO> voPage = new Page<>();
        BeanUtils.copyProperties(recommendedPosts, voPage, "records");

        List<PostVO> voList = recommendedPosts.getRecords().stream()
                .map(postService::toPostVO)
                .collect(Collectors.toList());

        voPage.setRecords(voList);
        return Result.success(voPage);
    }

    /**
     * POST /api/posts/search
     * 请求信息: JSON 请求体，包含 keyword, username, hashtag, page, size
     * 返回结果: posts（分页对象）
     * API说明: 搜索帖子接口，可按关键词（标题及内容）、发布者、标签或帖子分类过滤帖子
     */
    @SentinelResource(value = "post-api", blockHandler = "handleBlockPost")
    @PostMapping("/search")
    @Operation(
            summary = "搜索帖子",
            description = "支持按关键词（标题及内容）、发布者用户名、话题标签或帖子分类进行筛选，支持分页"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "搜索成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<Page<PostVO>> searchPosts(@RequestBody PostSearchRequest searchRequest) {
        Page<Post> posts = postService.searchPosts(
                searchRequest.getKeyword(),
                searchRequest.getHashtag(),
                searchRequest.getPage(),
                searchRequest.getSize()
        );
        // 构建 VO 分页对象
        Page<PostVO> voPage = new Page<>();
        BeanUtils.copyProperties(posts, voPage, "records");

        List<PostVO> voList = posts.getRecords().stream()
                .map(postService::toPostVO)
                .collect(Collectors.toList());
        voPage.setRecords(voList);
        return Result.success(voPage);
    }

    /**
     * GET /api/posts/detail
     * 请求信息: id
     * 返回结果: post详情
     * API说明: 查看帖子详情接口，根据帖子 id 获取帖子完整信息
     */
    @Operation(
            summary = "获取帖子详情（Query方式）",
            description = "根据帖子ID获取对应帖子的完整信息，使用请求参数传递ID"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功，返回帖子详情"),
            @ApiResponse(responseCode = "404", description = "未找到对应的帖子"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/detail")
    public Result<PostVO> getPostDetail(@RequestParam("id") String postId) {
        Post post = postService.getPostById(postId);
        //将post改成PostVO对象
        PostVO postVO = postService.toPostVO(post);
        return Result.success(postVO);
    }

    /**
     * GET /api/posts/categories
     * API说明: 获取所有的帖子分类信息
     */
    @GetMapping("/categories")
    @Operation(
            summary = "获取帖子分类",
            description = "返回系统中所有可用的帖子分类"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<List<PostCategory>> getPostCategories() {
        List<PostCategory> categories = postCategoryMapper.selectList(null);
        return Result.success(categories);
    }
    @Operation(
            summary = "发布帖子",
            description = "创建并发布一个新的帖子，前端传入 PostDTO"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "帖子发布成功"),
            @ApiResponse(responseCode = "401", description = "用户未登录或无权限"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping
    //@CachePut(key = "#result.data.id")
    public Result<?> create(@RequestBody PostCreateDTO dto) {
        // 从拦截器或UserHolder获取userId
        String userId = String.valueOf(UserHolder.getUser().getUserId());
        if(userId==null){
            return Result.error("未登录账号，请先登录");
        }

        return postService.createPost(dto, userId);

    }

    @Operation(
            summary = "获取帖子详情",
            description = "根据帖子ID获取帖子的详细信息"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功获取帖子详情"),
            @ApiResponse(responseCode = "404", description = "帖子不存在"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/{id}")
    //@CachePut(key = "#id")
    public PostVO detail(@PathVariable String id) {
        Post post = postService.getPostById(id);
        //将post改成PostVO对象
        PostVO postVO = postService.toPostVO(post);
        return postVO;
    }

    @Operation(
            summary = "更新帖子",
            description = "根据帖子ID和PostDTO更新帖子信息，需要帖子的创建者权限"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "帖子更新成功"),
            @ApiResponse(responseCode = "401", description = "用户未登录或无权限"),
            @ApiResponse(responseCode = "404", description = "帖子不存在"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PutMapping("/{id}")
    public Result<?> update(@PathVariable String id, @RequestBody PostCreateDTO  dto) {
        String userId = String.valueOf(UserHolder.getUser().getUserId());
        if(userId==null){
            return Result.error("未登录账号，请先登录");
        }
        return postService.updatePost(id, dto, userId);
    }

    @GetMapping("/user")
    @Operation(summary = "查询自己的所有帖子", description = "查询自己的所有帖子")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功，返回帖子列表"),
            @ApiResponse(responseCode = "401", description = "用户未登录或无权限"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<List<Post>> findPostsByUserIdSelf() {

        Long userID=UserHolder.getUser().getUserId();
        String id=String.valueOf(userID);
        // 如果需要，检查是否和当前登录用户匹配
        // String currentUserId = String.valueOf(UserHolder.getUser().getUserId());
        // if(!currentUserId.equals(uid)) { ... }


        List<Post> posts = postService.findByUserId(id);
        return Result.success(posts);
    }
    @GetMapping("/user/{user_id}")
    @Operation(summary = "查询某用户的所有帖子", description = "查询某用户的所有帖子")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功，返回帖子列表"),
            @ApiResponse(responseCode = "401", description = "用户未登录或无权限"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    public Result<List<Post>> findPostsByUserId(@PathVariable String user_id ) {
        List<Post> posts = postService.findByUserId(user_id);
        return Result.success(posts);
    }
    @Operation(summary = "根据帖子ID删除帖子", description = "删除帖子，需要当前用户或管理员权限")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "删除成功"),
            @ApiResponse(responseCode = "401", description = "无权限或未登录"),
            @ApiResponse(responseCode = "404", description = "帖子不存在"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @DeleteMapping("/{id}")
    public Result<?> deletePost(@PathVariable String id) {

        // 1. 查帖子信息
        Post old = postService.getPostById(id);
        if (old == null) {
            return Result.error("帖子不存在，无法删除");
        }
        // 2. 校验权限
        String userId = String.valueOf(UserHolder.getUser().getUserId());
        if (userId == null) {
            return Result.error("未登录账号，请先登录");
        }
        if (!old.getUserId().equals(userId)) {
            // 或者再判断是否是管理员用户
            return Result.error("无权删除该帖子");
        }
        // 3. 删除
        postService.deleteById(id);
        return Result.success("删除成功");
    }

    @Operation(
            summary = "获取帖子点赞数",
            description = "根据帖子 ID 返回该帖子的点赞总数"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "400", description = "参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/{postId}/likes")
    public Result<Integer> getLikeCount(@Parameter(description = "帖子ID", required = true)
                                        @PathVariable String postId) {
        int likeCount = postService.getLikeCount(postId);
        return Result.success(likeCount);
    }
    @Operation(
            summary = "获取帖子评论数",
            description = "根据帖子 ID 返回该帖子的评论总数"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "400", description = "参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/{postId}/comments/count")
    public Result<Integer> getCommentCount(@Parameter(description = "帖子ID", required = true)
                                           @PathVariable String postId) {
        int commentCount = postService.getCommentCount(postId);
        return Result.success(commentCount);
    }
    @Operation(
            summary = "获取帖子收藏数",
            description = "根据帖子 ID 返回该帖子的收藏总数"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "400", description = "参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/{postId}/favorites")
    public Result<Integer> getFavoriteCount(
            @Parameter(description = "帖子ID", required = true)
            @PathVariable String postId) {

        int favoriteCount = postService.getCollectionCount(postId);
        return Result.success(favoriteCount);
    }

    // 限流时调用的方法，参数和原方法一致 + BlockException
    public Result<Page<PostVO>> handleBlockPost(PostSearchRequest searchRequest, BlockException ex) {
        return Result.error("请求被限流");
    }
}
